/**
 * io_stream.c
 *
 *  Created on: 2019-09-05
 *      Author: chenshisheng
 */

#include "stream/io_stream.h"
#include "message_queue.h"
#include "shell.h"

int IoStream_OnRx(IoStream_t *is, const void *data, unsigned int size)
{
    const uint8_t *buf = data;
    int rsize = 0;
    int ret = 0;

    for(unsigned int i = 0; i < size; i++)
    {
        char c = buf[i];

        ret = Stream_Put(&is->rbuf, c);
        if(ret == 1)
        {
            rsize ++;
            if(c == '\n')
            {
                // 发送信号给shell
                Stream_LineSignal_t sig;

                sig.stream = (Stream_t *)is;
                sig.tail = c;
                Shell_SendLineSignal(&sig);
            }
        }
        else
        {
            break;
        }
    }

    return rsize;
}

void _Flush(void *stream)
{
    IoStream_t *is = stream;
    MemStream_t *ms = &is->tbuf;

    if(MemStream_DataSize(ms) == 0)
    {
        return;
    }

    is->tx(stream, MemStream_Data(ms), MemStream_DataSize(ms));
    Stream_Flush(ms);
}

int _Put(void *stream, unsigned char b)
{
    IoStream_t *is = stream;

    if(MemStream_Space(&is->tbuf) == 0)
    {
        Stream_Flush(stream);
    }

    int ret = Stream_Put(&is->tbuf, b);
    if(b == '\n')
    {
        Stream_Flush(stream);
    }

    return ret;
}

static int _Get(void *stream, unsigned char *pb)
{
    IoStream_t *is = stream;

    return Stream_Get(&is->rbuf, pb);
}

/**
 *
 * @param is IO stream指针
 * @param inputBuf 输入缓存
 * @param bufSize  缓存大小
 * @param put  输出加调函数
 * @param userData  用户数据
 * @note  缓存大小必须为2的n次方
 */
int IoStream_Init(
        IoStream_t *is,
        void *rxBuf,
        unsigned int rxBufSize,
        void *txBuf,
        unsigned int txBufSize,
        Stream_Tx_t tx,
        int userData)
{
    is->tx = tx;
    is->userData = userData;

    MemStream_Init(&is->rbuf, rxBuf, rxBufSize);
    MemStream_Init(&is->tbuf, txBuf, txBufSize);
    return Stream_Init(&is->stream, _Put, _Get, _Flush, true);
}

int IoStream_InitWithoutBuffer(IoStream_t *is, Stream_Put_t put, Stream_Get_t get, Stream_Flush_t flush, int userData)
{
    is->userData = userData;

    MemStream_Init(&is->rbuf, NULL, 0);
    MemStream_Init(&is->tbuf, NULL, 0);
    return Stream_Init(&is->stream, put, get, flush, true);
}
